[[!meta date="2017-08-14T10:22:07,537945254-06:00"]]
[[!meta author="Tyler Cipriani"]]
[[!meta copyright="""
Copyright &copy; 2017 Tyler Cipriani
"""]]
[[!meta title="Offline spellcheck"]]
[[!tag computing]]

In which I futilely attempt to use `aspell` to stop using Google as
spellcheck.

I am embarrassingly atrocious at spelling. In Vim, which I use for
email via Mutt, I can use `:set spell`. In Emacs I can use
`flyspell-mode`. Browsers all have spellcheck now, seemingly. Still...
sometimes I find myself just Googling™ (or DDGing™) individual words
as I flail through the darkness that is spelling in the English
language. This is stupid and ridiculous for myriad reasons that I
don't really want to talk about.

As is my wont, through force of will, by might of `awk`, and by glory
of `xsel`: I have written a function in my dotfiles that solves this
problem for me. It _might_ even be generally useful, bask in its
awesomeness:

![spell function in action][]

```
spell() {
    local candidates oldifs word array_pos
    oldifs="$IFS"
    IFS=':'

    # Parse the apsell format and return a list of ":" separated words
    read -a candidates <<< "$(printf "%s\n" "$1" \
        | aspell -a \
        | awk -F':' '/^&/ {
            split($2, a, ",")
            result=""
            for (x in a) {
                gsub(/^[ \t]/, "", a[x])
                result = a[x] ":" result
            }
            gsub(/:$/, "", result)
            print result
        }')"

    # Reverse number and print the parsed bash array because the list comes
    # out of gawk backwards
    for item in "${candidates[@]}"; do
        printf '%s\n' "$item"
    done \
        | tac \
        | nl \
        | less -FirSX

    printf "[ $(tput setaf 2)?$(tput sgr0) ]\t%s" \
        'Enter the choice (empty to cancel, 0 for input): '
    read index

    \[[ -z "$index" ]] && return
    \[[  "$index" == 0 ]] && word="$1"

    \[[ -z "$word" ]] && {
        array_pos=$(( ${#candidates[@]} - index ))
        word="${candidates[$array_pos]}"
    }

    \[[ -n "$word" ]] && {
        printf "$word" | xsel -p
        printf "Copied '%s' to clipboard!\n" "$word"
    } || printf "[ $(tput setaf 1):($(tput sgr0) ] %s\n" 'No match found'


    IFS="$oldifs"
}
```

Maybe someone can use this `¯\_(ツ)_/¯`

[spell function in action]: https://photos.tylercipriani.com/thumbs/od/46c92a641342553f36e77e406e1613/original.gif